{
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "Tce3stUlHN0L"
      },
      "source": [
        "##### Copyright 2020 The TensorFlow Authors."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "cellView": "form",
        "id": "IcfrhafzkZbH"
      },
      "outputs": [],
      "source": [
        "#@title Licensed under the Apache License, Version 2.0 (the \"License\");\n",
        "# you may not use this file except in compliance with the License.\n",
        "# You may obtain a copy of the License at\n",
        "#\n",
        "# https://www.apache.org/licenses/LICENSE-2.0\n",
        "#\n",
        "# Unless required by applicable law or agreed to in writing, software\n",
        "# distributed under the License is distributed on an \"AS IS\" BASIS,\n",
        "# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n",
        "# See the License for the specific language governing permissions and\n",
        "# limitations under the License."
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "qFdPvlXBOdUN"
      },
      "source": [
        "# 잘라내기 종합 가이드"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "MfBg1C5NB3X0"
      },
      "source": [
        "<table class=\"tfo-notebook-buttons\" align=\"left\">\n",
        "  <td><a target=\"_blank\" href=\"https://www.tensorflow.org/model_optimization/guide/pruning/comprehensive_guide\"><img src=\"https://www.tensorflow.org/images/tf_logo_32px.png\">}TensorFlow.org에서 보기</a></td>\n",
        "  <td><a target=\"_blank\" href=\"https://colab.research.google.com/github/tensorflow/model-optimization/blob/master/tensorflow_model_optimization/g3doc/guide/pruning/comprehensive_guide.ipynb\"><img src=\"https://www.tensorflow.org/images/colab_logo_32px.png\">Google Colab에서 실행하기</a></td>\n",
        "  <td><a target=\"_blank\" href=\"https://github.com/tensorflow/model-optimization/blob/master/tensorflow_model_optimization/g3doc/guide/pruning/comprehensive_guide.ipynb\"><img src=\"https://www.tensorflow.org/images/GitHub-Mark-32px.png\">GitHub에서소스 보기</a></td>\n",
        "  <td><a href=\"https://storage.googleapis.com/tensorflow_docs/model-optimization/tensorflow_model_optimization/g3doc/guide/pruning/comprehensive_guide.ipynb\"><img src=\"https://www.tensorflow.org/images/download_logo_32px.png\">노트북 다운로드하기</a></td>\n",
        "</table>"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "FbORZA_bQx1G"
      },
      "source": [
        "Keras 가중치 잘라내기에 대한 종합 가이드를 시작합니다.\n",
        "\n",
        "이 페이지는 다양한 사용 사례를 문서화하고 각각에 대해 API를 사용하는 방법을 보여줍니다. 필요한 API를 알고 나면, [API 문서](https://www.tensorflow.org/model_optimization/api_docs/python/tfmot/sparsity)에서 매개변수와 하위 수준의 세부 정보를 찾아보세요.\n",
        "\n",
        "- 잘라내기의 이점과 지원되는 기능을 보려면 [개요](https://www.tensorflow.org/model_optimization/guide/pruning)를 참조하세요.\n",
        "- 단일 엔드 투 엔드 예는 [잘라내기 예](https://www.tensorflow.org/model_optimization/guide/pruning/pruning_with_keras)를 참조하세요.\n",
        "\n",
        "다음 사용 사례를 다룹니다.\n",
        "\n",
        "- 잘라낸 모델을 정의하고 훈련합니다.\n",
        "    - 순차 및 함수형\n",
        "    - Keras model.fit 및 사용자 정의 훈련 루프\n",
        "- 잘라낸 모델을 체크포인트 지정하고 역직렬화합니다.\n",
        "- 잘라낸 모델을 배포하고 압축 이점을 확인합니다.\n",
        "\n",
        "잘라내기 알고리즘의 구성에 대해서는 `tfmot.sparsity.keras.prune_low_magnitude` API 문서를 참조하세요."
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "nuABqZnXVDvO"
      },
      "source": [
        "## 설정"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "u9mRDekZEfnR"
      },
      "source": [
        "필요한 API를 찾고 목적을 이해하기 위해 실행할 수 있지만, 이 섹션은 건너뛸 수 있습니다."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "cellView": "both",
        "id": "lvpH1Hg7ULFz"
      },
      "outputs": [],
      "source": [
        "! pip install -q tensorflow-model-optimization\n",
        "\n",
        "import tensorflow as tf\n",
        "import numpy as np\n",
        "import tensorflow_model_optimization as tfmot\n",
        "\n",
        "%load_ext tensorboard\n",
        "\n",
        "import tempfile\n",
        "\n",
        "input_shape = [20]\n",
        "x_train = np.random.randn(1, 20).astype(np.float32)\n",
        "y_train = tf.keras.utils.to_categorical(np.random.randn(1), num_classes=20)\n",
        "\n",
        "def setup_model():\n",
        "  model = tf.keras.Sequential([\n",
        "      tf.keras.layers.Dense(20, input_shape=input_shape),\n",
        "      tf.keras.layers.Flatten()\n",
        "  ])\n",
        "  return model\n",
        "\n",
        "def setup_pretrained_weights():\n",
        "  model = setup_model()\n",
        "\n",
        "  model.compile(\n",
        "      loss=tf.keras.losses.categorical_crossentropy,\n",
        "      optimizer='adam',\n",
        "      metrics=['accuracy']\n",
        "  )\n",
        "\n",
        "  model.fit(x_train, y_train)\n",
        "\n",
        "  _, pretrained_weights = tempfile.mkstemp('.tf')\n",
        "\n",
        "  model.save_weights(pretrained_weights)\n",
        "\n",
        "  return pretrained_weights\n",
        "\n",
        "def get_gzipped_model_size(model):\n",
        "  # Returns size of gzipped model, in bytes.\n",
        "  import os\n",
        "  import zipfile\n",
        "\n",
        "  _, keras_file = tempfile.mkstemp('.h5')\n",
        "  model.save(keras_file, include_optimizer=False)\n",
        "\n",
        "  _, zipped_file = tempfile.mkstemp('.zip')\n",
        "  with zipfile.ZipFile(zipped_file, 'w', compression=zipfile.ZIP_DEFLATED) as f:\n",
        "    f.write(keras_file)\n",
        "\n",
        "  return os.path.getsize(zipped_file)\n",
        "\n",
        "setup_model()\n",
        "pretrained_weights = setup_pretrained_weights()"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "TZyLYFTER4aP"
      },
      "source": [
        "## 모델 정의하기"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "Ybigft1fTn4T"
      },
      "source": [
        "### 전체 모델 잘라내기(순차 및 함수형)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "puZvqnp1xsn-"
      },
      "source": [
        "**모델 정확성의 향상을 위한 팁:**\n",
        "\n",
        "- 정확성을 가장 많이 떨어뜨리는 레이어 잘라내기를 건너뛰려면 \"일부 레이어 잘라내기\"를 시도합니다.\n",
        "- 일반적으로 처음부터 훈련하는 것보다 잘라내기로 미세 조정하는 것이 좋습니다.\n",
        "\n",
        "잘라내기로 전체 모델을 훈련하려면, `tfmot.sparsity.keras.prune_low_magnitude`를 모델에 적용합니다.\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "aIn-hFO_T_PU"
      },
      "outputs": [],
      "source": [
        "base_model = setup_model()\n",
        "base_model.load_weights(pretrained_weights) # optional but recommended.\n",
        "\n",
        "model_for_pruning = tfmot.sparsity.keras.prune_low_magnitude(base_model)\n",
        "\n",
        "model_for_pruning.summary()"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "xTbTLn3dZM7h"
      },
      "source": [
        "### 일부 레이어 잘라내기(순차 및 함수형)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "MbM8o832xTxV"
      },
      "source": [
        "모델을 잘라내면 정확성에 부정적인 영향을 미칠 수 있습니다. 모델의 레이어를 선택적으로 잘라내어 정확성, 속도 및 모델 크기 간의 균형을 탐색할 수 있습니다.\n",
        "\n",
        "**모델 정확성의 향상을 위한 팁:**\n",
        "\n",
        "- 일반적으로 처음부터 훈련하는 것보다 잘라내기로 미세 조정하는 것이 좋습니다.\n",
        "- 첫 번째 레이어 대신 이후 레이어를 잘라냅니다.\n",
        "- 중요 레이어(예: attention 메커니즘)을 잘라내지 마세요.\n",
        "\n",
        "**추가 자료**:\n",
        "\n",
        "- `tfmot.sparsity.keras.prune_low_magnitude` API 문서는 레이어별로 잘라내기 구성을 변경하는 방법에 대한 세부 정보를 제공합니다.\n",
        "\n",
        "아래 예에서는 `Dense` 레이어만 잘라냅니다."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "HN0B_QB-ZhE2"
      },
      "outputs": [],
      "source": [
        "# Create a base model\n",
        "base_model = setup_model()\n",
        "base_model.load_weights(pretrained_weights) # optional but recommended for model accuracy\n",
        "\n",
        "# Helper function uses `prune_low_magnitude` to make only the \n",
        "# Dense layers train with pruning.\n",
        "def apply_pruning_to_dense(layer):\n",
        "  if isinstance(layer, tf.keras.layers.Dense):\n",
        "    return tfmot.sparsity.keras.prune_low_magnitude(layer)\n",
        "  return layer\n",
        "\n",
        "# Use `tf.keras.models.clone_model` to apply `apply_pruning_to_dense` \n",
        "# to the layers of the model.\n",
        "model_for_pruning = tf.keras.models.clone_model(\n",
        "    base_model,\n",
        "    clone_function=apply_pruning_to_dense,\n",
        ")\n",
        "\n",
        "model_for_pruning.summary()"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "HiA28PrrW11H"
      },
      "source": [
        "이 예에서는 레이어 유형을 사용하여 잘라낼 레이어를 결정했지만, 특정 레이어를 잘라내는 가장 쉬운 방법은 `name` 속성을 설정하고 `clone_function`에서 해당 내용을 찾는 것입니다."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "CjY_JyB808Da"
      },
      "outputs": [],
      "source": [
        "print(base_model.layers[0].name)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "mpb_BydRaSoF"
      },
      "source": [
        "#### 읽기 더 쉽지만 잠재적으로 모델 정확성이 낮음"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "2vqXeYffzSHp"
      },
      "source": [
        "잘라내기를 사용한 미세 조정과 호환되지 않으므로 미세 조정을 지원하는 위의 예보다 정확성이 떨어질 수 있습니다.\n",
        "\n",
        "초기 모델을 정의하는 동안 `prune_low_magnitude`를 적용할 수 있지만, 이후에 가중치를 로드하면 아래 예에서 동작하지 않습니다."
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "s5p5jvH5KznJ"
      },
      "source": [
        "**함수형 예**"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "7Wow55hg5oiM"
      },
      "outputs": [],
      "source": [
        "# Use `prune_low_magnitude` to make the `Dense` layer train with pruning.\n",
        "i = tf.keras.Input(shape=(20,))\n",
        "x = tfmot.sparsity.keras.prune_low_magnitude(tf.keras.layers.Dense(10))(i)\n",
        "o = tf.keras.layers.Flatten()(x)\n",
        "model_for_pruning = tf.keras.Model(inputs=i, outputs=o)\n",
        "\n",
        "model_for_pruning.summary()"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "wIGj-r2of2ls"
      },
      "source": [
        "**순차 예**\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "mQOiDUGgfi4y"
      },
      "outputs": [],
      "source": [
        "# Use `prune_low_magnitude` to make the `Dense` layer train with pruning.\n",
        "model_for_pruning = tf.keras.Sequential([\n",
        "  tfmot.sparsity.keras.prune_low_magnitude(tf.keras.layers.Dense(20, input_shape=input_shape)),\n",
        "  tf.keras.layers.Flatten()\n",
        "])\n",
        "\n",
        "model_for_pruning.summary()"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "vnMguvVSnUqD"
      },
      "source": [
        "### 사용자 정의 Keras 레이어를 잘라내거나 잘라낼 레이어의 일부를 수정합니다."
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "BLgH1aFMjTK4"
      },
      "source": [
        "**일반적인 실수:** 바이어스를 제거하면 일반적으로 모델 정확성이 너무 많이 손상됩니다.\n",
        "\n",
        "`tfmot.sparsity.keras.PrunableLayer`는 두 가지 사용 사례를 제공합니다.\n",
        "\n",
        "1. 사용자 정의 Keras 레이어를 잘라냅니다.\n",
        "2. 내장 Keras 레이어의 일부를 수정하여 잘라냅니다.\n",
        "\n",
        "예를 들어, API는 기본적으로 `Dense` 레이어의 커널만 잘라냅니다. 아래의 예는 바이어스도 제거합니다.\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "77jgBjccnTh6"
      },
      "outputs": [],
      "source": [
        "class MyDenseLayer(tf.keras.layers.Dense, tfmot.sparsity.keras.PrunableLayer):\n",
        "\n",
        "  def get_prunable_weights(self):\n",
        "    # Prune bias also, though that usually harms model accuracy too much.\n",
        "    return [self.kernel, self.bias]\n",
        "\n",
        "# Use `prune_low_magnitude` to make the `MyDenseLayer` layer train with pruning.\n",
        "model_for_pruning = tf.keras.Sequential([\n",
        "  tfmot.sparsity.keras.prune_low_magnitude(MyDenseLayer(20, input_shape=input_shape)),\n",
        "  tf.keras.layers.Flatten()\n",
        "])\n",
        "\n",
        "model_for_pruning.summary()\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "itAyTyzvRroH"
      },
      "source": [
        "## 모델 훈련하기"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "y4hnWH2NY5MO"
      },
      "source": [
        "### Model.fit"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "_LYCDIunTE9B"
      },
      "source": [
        "훈련 중에 `tfmot.sparsity.keras.UpdatePruningStep` 콜백을 호출합니다.\n",
        "\n",
        "훈련 디버깅에 `tfmot.sparsity.keras.PruningSummaries` 콜백을 사용합니다."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "fKZ2PxcpY_WV"
      },
      "outputs": [],
      "source": [
        "# Define the model.\n",
        "base_model = setup_model()\n",
        "base_model.load_weights(pretrained_weights) # optional but recommended for model accuracy\n",
        "model_for_pruning = tfmot.sparsity.keras.prune_low_magnitude(base_model)\n",
        "\n",
        "log_dir = tempfile.mkdtemp()\n",
        "callbacks = [\n",
        "    tfmot.sparsity.keras.UpdatePruningStep(),\n",
        "    # Log sparsity and other metrics in Tensorboard.\n",
        "    tfmot.sparsity.keras.PruningSummaries(log_dir=log_dir)\n",
        "]\n",
        "\n",
        "model_for_pruning.compile(\n",
        "      loss=tf.keras.losses.categorical_crossentropy,\n",
        "      optimizer='adam',\n",
        "      metrics=['accuracy']\n",
        ")\n",
        "\n",
        "model_for_pruning.fit(\n",
        "    x_train,\n",
        "    y_train,\n",
        "    callbacks=callbacks,\n",
        "    epochs=2,\n",
        ")\n",
        "\n",
        "#docs_infra: no_execute\n",
        "%tensorboard --logdir={log_dir}"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "6kcuGmf5MSnJ"
      },
      "source": [
        "Colab이 아닌 사용자의 경우, [TensorBoard.dev](https://tensorboard.dev/experiment/XiNXEBjHQ3Oabc6jRLKiXQ/#scalars&_smoothingWeight=0)에서 이 코드 블록의 [이전 실행의 결과](https://tensorboard.dev/)를 볼 수 있습니다."
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "pDcSvbNdZA-1"
      },
      "source": [
        "### 사용자 정의 훈련 루프"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "uQA8GaD6T3-o"
      },
      "source": [
        "훈련 중에 `tfmot.sparsity.keras.UpdatePruningStep` 콜백을 호출합니다.\n",
        "\n",
        "To help debug training, use the `tfmot.sparsity.keras.PruningSummaries` callback."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "hPQUrkodbIF2"
      },
      "outputs": [],
      "source": [
        "# Define the model.\n",
        "base_model = setup_model()\n",
        "base_model.load_weights(pretrained_weights) # optional but recommended for model accuracy\n",
        "model_for_pruning = tfmot.sparsity.keras.prune_low_magnitude(base_model)\n",
        "\n",
        "# Boilerplate\n",
        "loss = tf.keras.losses.categorical_crossentropy\n",
        "optimizer = tf.keras.optimizers.Adam()\n",
        "log_dir = tempfile.mkdtemp()\n",
        "unused_arg = -1\n",
        "epochs = 2\n",
        "batches = 1 # example is hardcoded so that the number of batches cannot change.\n",
        "\n",
        "# Non-boilerplate.\n",
        "model_for_pruning.optimizer = optimizer\n",
        "step_callback = tfmot.sparsity.keras.UpdatePruningStep()\n",
        "step_callback.set_model(model_for_pruning)\n",
        "log_callback = tfmot.sparsity.keras.PruningSummaries(log_dir=log_dir) # Log sparsity and other metrics in Tensorboard.\n",
        "log_callback.set_model(model_for_pruning)\n",
        "\n",
        "step_callback.on_train_begin() # run pruning callback\n",
        "for _ in range(epochs):\n",
        "  log_callback.on_epoch_begin(epoch=unused_arg) # run pruning callback\n",
        "  for _ in range(batches):\n",
        "    step_callback.on_train_batch_begin(batch=unused_arg) # run pruning callback\n",
        "\n",
        "    with tf.GradientTape() as tape:\n",
        "      logits = model_for_pruning(x_train, training=True)\n",
        "      loss_value = loss(y_train, logits)\n",
        "      grads = tape.gradient(loss_value, model_for_pruning.trainable_variables)\n",
        "      optimizer.apply_gradients(zip(grads, model_for_pruning.trainable_variables))\n",
        "\n",
        "  step_callback.on_epoch_end(batch=unused_arg) # run pruning callback\n",
        "\n",
        "#docs_infra: no_execute\n",
        "%tensorboard --logdir={log_dir}"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "vh4lJt4zMh1v"
      },
      "source": [
        "Colab이 아닌 사용자의 경우, [TensorBoard.dev](https://tensorboard.dev/experiment/jDeGzF3xQeSyb7Qir1ZcBQ/#scalars&_smoothingWeight=0)에서 이 코드 블록의 [이전 실행의 결과](https://tensorboard.dev/)를 볼 수 있습니다."
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "o8H-8lQ-cPa-"
      },
      "source": [
        "### 잘라낸 모델의 정확성 향상하기\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "Y2t4fYXvAV1V"
      },
      "source": [
        "먼저, `tfmot.sparsity.keras.prune_low_magnitude` API 문서를 보고 잘라내기 일정이 무엇인지, 그리고 각 잘라내기 일정 유형의 수학을 이해합니다.\n",
        "\n",
        "**팁**:\n",
        "\n",
        "- 모델이 잘라내기를 수행할 때 학습률이 너무 높거나 낮지 않습니다. [잘라내기 일정](https://www.tensorflow.org/model_optimization/api_docs/python/tfmot/sparsity/keras/PruningSchedule)을 하이퍼 매개변수로 간주합니다.\n",
        "\n",
        "- 빠른 테스트로, `tfmot.sparsity.keras.ConstantSparsity` 일정으로 `begin_step`을 0으로 설정하여 훈련 시작 시 모델을 최종 희소성까지 잘라내는 실험을 시도해 보세요. 운이 좋으면 우수한 결과를 얻을 수도 있습니다.\n",
        "\n",
        "- 모델이 복구할 시간을 주기 위해 자주 잘라내기를 수행하지 마세요. [잘라내기 일정](https://www.tensorflow.org/model_optimization/api_docs/python/tfmot/sparsity/keras/PruningSchedule)에서 적절한 기본 빈도를 제공합니다.\n",
        "\n",
        "- 모델 정확성을 개선하기 위한 일반적인 아이디어는 '모델 정의하기'에서 사용 사례에 대한 팁을 찾아보세요."
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "MpvX5IqahV1r"
      },
      "source": [
        "## 체크포인트 및 역직렬화"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "GuZ5wlij1dcJ"
      },
      "source": [
        "체크포인트 중에 옵티마이저 단계를 보존해야 합니다. 즉, 체크포인트 지정을 위해 Keras HDF5 모델을 사용할 수 있지만, Keras HDF5 가중치는 사용할 수 없습니다."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "6khQg-q7imfH"
      },
      "outputs": [],
      "source": [
        "# Define the model.\n",
        "base_model = setup_model()\n",
        "base_model.load_weights(pretrained_weights) # optional but recommended for model accuracy\n",
        "model_for_pruning = tfmot.sparsity.keras.prune_low_magnitude(base_model)\n",
        "\n",
        "_, keras_model_file = tempfile.mkstemp('.h5')\n",
        "\n",
        "# Checkpoint: saving the optimizer is necessary (include_optimizer=True is the default).\n",
        "model_for_pruning.save(keras_model_file, include_optimizer=True)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "H-CLxooLYnRN"
      },
      "source": [
        "위의 코드가 일반적으로 적용됩니다. 아래 코드는 HDF5 모델 형식(HDF5 가중치 및 기타 형식이 아님)에만 필요합니다.\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "2nGC1hZnYlzb"
      },
      "outputs": [],
      "source": [
        "# Deserialize model.\n",
        "with tfmot.sparsity.keras.prune_scope():\n",
        "  loaded_model = tf.keras.models.load_model(keras_model_file)\n",
        "\n",
        "loaded_model.summary()"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "jew8M217SgQw"
      },
      "source": [
        "## 잘라낸 모델 배포하기"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "2uj4SfF1cnTR"
      },
      "source": [
        "### 크기 압축으로 모델 내보내기"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "57uNm47L4Yro"
      },
      "source": [
        "**일반적인 실수**: 잘라내기의 압축 이점을 확인하려면, `strip_pruning`과 표준 압축 알고리즘(예: gzip을 통해)을 적용하는 것이 모두 필요합니다."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "EZ3TD8cYkxZM"
      },
      "outputs": [],
      "source": [
        "# Define the model.\n",
        "base_model = setup_model()\n",
        "base_model.load_weights(pretrained_weights) # optional but recommended for model accuracy\n",
        "model_for_pruning = tfmot.sparsity.keras.prune_low_magnitude(base_model)\n",
        "\n",
        "# Typically you train the model here.\n",
        "\n",
        "model_for_export = tfmot.sparsity.keras.strip_pruning(model_for_pruning)\n",
        "\n",
        "print(\"final model\")\n",
        "model_for_export.summary()\n",
        "\n",
        "print(\"\\n\")\n",
        "print(\"Size of gzipped pruned model without stripping: %.2f bytes\" % (get_gzipped_model_size(model_for_pruning)))\n",
        "print(\"Size of gzipped pruned model with stripping: %.2f bytes\" % (get_gzipped_model_size(model_for_export)))"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "qPXvYIHOctem"
      },
      "source": [
        "### 하드웨어별 최적화"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "yqk0jI49c1mw"
      },
      "source": [
        "여러 백엔드에서 [잘라내기를 사용하여 지연 시간을 개선]((https://github.com/tensorflow/model-optimization/issues/173))하면, 블록 희소성을 사용하여 특정 하드웨어의 지연 시간을 개선할 수 있습니다.\n",
        "\n",
        "블록 크기를 늘리면 대상 모델의 정확성에 대해 달성할 수 있는 최대 희소성이 감소합니다. 그럼에도 불구하고, 지연 시간은 여전히 개선될 수 있습니다.\n",
        "\n",
        "블록 희소성에 지원되는 항목에 대한 자세한 내용은 `tfmot.sparsity.keras.prune_low_magnitude` API 문서를 참조하세요."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "xedaVDeFc0bw"
      },
      "outputs": [],
      "source": [
        "base_model = setup_model()\n",
        "\n",
        "# For using intrinsics on a CPU with 128-bit registers, together with 8-bit\n",
        "# quantized weights, a 1x16 block size is nice because the block perfectly\n",
        "# fits into the register.\n",
        "pruning_params = {'block_size': [1, 16]}\n",
        "model_for_pruning = tfmot.sparsity.keras.prune_low_magnitude(base_model, **pruning_params)\n",
        "\n",
        "model_for_pruning.summary()"
      ]
    }
  ],
  "metadata": {
    "colab": {
      "collapsed_sections": [
        "Tce3stUlHN0L"
      ],
      "name": "comprehensive_guide.ipynb",
      "toc_visible": true
    },
    "kernelspec": {
      "display_name": "Python 3",
      "name": "python3"
    }
  },
  "nbformat": 4,
  "nbformat_minor": 0
}
